//
//  ReversiBoard.h
//  Reversi
//	リバーシボードモデルクラス
//
//  Created by 成瀬 龍人 on 2/4/10.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "ReversiBoardLineRange.h"

//	石
typedef enum _RversiStone {
	REVERSI_STONE_BLACK = 0,
	REVERSI_STONE_WHITE = 1
} ReversiStone;

//	石をReversiStoneを表記文字に変換
#define ReversiStone2String(stone) ((stone == REVERSI_STONE_BLACK) ? @"@" : @"O")

//	ReversiBoardPositionから座標の位置のみビットが立っているマスクに変換
#define pos2mask(pos)     ((uint64)((uint64)1 << (64 - (((pos).x) + ((pos).y - 1) * 8))))
//	座標の位置のみビットが立っているマスクに変換
#define int2mask(x,y)     ((uint64)((uint64)1 << (64 - ((x) + ((y) - 1) * 8))))
//	index番目のビットのみが立っているマスクに変換
#define index2mask(index) ((uint64)((uint64)1 << (64 - (index))))
//	ビットを右方向に移動
#define transferR(mask)   ((mask >> 1) & 0x7f7f7f7f7f7f7f7f)
//	ビットを左方向に移動
#define transferL(mask)   ((mask << 1) & 0xfefefefefefefefe)
//	ビットを下方向に移動
#define transferD(mask)   ((mask >> 8))
//	ビットを上方向に移動
#define transferU(mask)   ((mask << 8))
//	ビットを右上方向に移動
#define transferUR(mask)  ((mask << 7) & 0x7f7f7f7f7f7f7f7f)
//	ビットを左上方向に移動
#define transferUL(mask)  ((mask << 9) & 0xfefefefefefefefe)
//	ビットを右下方向に移動
#define transferDR(mask)  ((mask >> 9) & 0x7f7f7f7f7f7f7f7f)
//	ビットを左下方向に移動
#define transferDL(mask)  ((mask >> 7) & 0xfefefefefefefefe)

@interface ReversiBoard : NSObject <NSCopying> {
	//	黒が置いてある場所がビットが立っているマスク
	uint64 black;
	//	白が置いてある場所がビットが立っているマスク
	uint64 white;
}

//	立っているビットを数え上げる
+ (int)countBitNum:(uint64)mask;

//	何も置いていない状態でボードを初期化
- (id)init;

//	ゲーム開始状態でボードを初期化
- (id)initForGame;

//	ボードを表した文字列で初期化
//	@が黒、Oが白、+が何も無い
//	ex)"+++++++++++++++++++++++++++@O++++++O@+++++++++++++++++++++++++++"
- (id)initWithString:(NSString*)board;

//	石を置く
//	@param	stone	石の種類
//	@param	stone	置く場所
- (void)put:(ReversiStone)stone:(ReversiBoardPosition*)pos;
- (void)put:(ReversiStone)stone mask:(uint64)pos;

//	石を取り除く
//	@param	pos	取り除く場所
- (void)clear:(ReversiBoardPosition*)pos;
- (void)clearWithMask:(uint64)pos;

//	すべての石を取り除く
- (void)allClear;

//	石が置いているか確認
//	@param	stone	石の種類
//	@param	stone	置く場所
- (bool)is:(ReversiStone)stone:(ReversiBoardPosition*)pos;
- (bool)is:(ReversiStone)stone mask:(uint64)pos;

//	石が何も置いていないか確認
//	@param	stone	石の種類
//	@param	stone	置く場所
- (bool)isFree:(ReversiBoardPosition*)pos;
- (bool)isFreeWithMask:(uint64)pos;

//	ボードが石で埋まっているか確認
- (bool)isFull;

//	ゲームが終了しているか確認
- (bool)isGameOver;

//	石を置ける事の出来る座標(ReversiBoardPosition)の配列を取得
//	@param	stone	石の種類
- (NSArray*)allocatablePositions:(ReversiStone)stone;

//	石を置ける場所の数
//	@param	stone	石の種類
- (int)allocatablePositionsNum:(ReversiStone)stone;

//	置かれている石の数
//	@param	stone	石の種類
- (int)numberOf:(ReversiStone)stone;

//	石が置かれていない場所の数
- (int)numberOfFree;

//	白と黒を反転
- (void)invert;

//	置いていい場所かどうか確認
//	@param	stone	石の種類
//	@param	pos		置く場所
- (bool)isPutOK:(ReversiStone)stone:(ReversiBoardPosition*)pos;
- (bool)isPutOK:(ReversiStone)stone mask:(uint64)pos;

//	石を置いて、返せる場所の石を返す
//	@param	stone	石の種類
//	@param	pos		置く場所
- (void)putAndChange:(ReversiStone)stone:(ReversiBoardPosition*)pos;
- (uint64)putAndChange:(ReversiStone)stone mask:(uint64)pos;

//	石を置いて、返せる場所の石を返す．戻り値として返した線分(ReversiBoardLineRange)の配列を取得
//	@param	stone	石の種類
//	@param	pos		置く場所
- (NSArray*)putAndChangeEx:(ReversiStone)stone:(ReversiBoardPosition*)pos;
- (NSArray*)putAndChangeEx:(ReversiStone)stone mask:(uint64)mask pos:(ReversiBoardPosition*)pos;

//	石を置いたときに返すことの出来る石の数
//	@param	stone	石の種類
//	@param	pos		置く場所
- (int)numberOfWillChange:(ReversiStone)stone:(ReversiBoardPosition*)pos;
- (int)numberOfWillChange:(ReversiStone)stone mask:(uint64)pos;


//	ボードの内容を文字列で取得
//	ex)
//		++++++++
//		++++++++
//		++++++++
//		+++@O+++
//		+++O@+++
//		++++++++
//		++++++++
//		++++++++
- (NSString*)description;

//	同値
- (bool)isEqual:(id)object;

//	コピー
- (id)copyWithZone:(NSZone*)zone;

@end
